package com.xlf.service.base.service.importProblem.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.UnicodeUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.xlf.common.core.exception.BizException;
import com.xlf.pojo.base.Language;
import com.xlf.pojo.base.Problem;
import com.xlf.pojo.base.ProblemCase;
import com.xlf.pojo.base.ProblemLanguage;
import com.xlf.service.base.pojo.vo.ImportProblemVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author xlf 2734029211@qq.com
 * @Date 2024/1/16 16:55
 * @Description: TODO
 * @Version 1.0
 */
@Service
public class QDUOJProblemImportService extends ProblemImportService{


    public void test(String workFileDir){

        File fileDir = new File(workFileDir);

        File[] files = fileDir.listFiles();

        //系统语言
        Map<String, Language> languageMap = getLanguageMap();

        ArrayList<Problem> problems = new ArrayList<>();

        //系统标签
        Map<String, Long> tagMap = getTagMap();
        for (File item : files) {

            if(!item.isDirectory())
                continue;

            File[] t = item.listFiles();

            HashMap<String, File> jsonFile = getJSONFile(t);
            File problemF = jsonFile.get("problem");
            JSONObject jsonObject = JSONUtil.parseObj(FileUtil.readString(problemF, StandardCharsets.UTF_8));
            Problem problem = toBaseProblem(jsonObject);

            //获取测试用例
            HashMap<String, File> testcaseFile = getTestcaseFile(t);
            File testCase = testcaseFile.get("testcase");
            setProblemCase(problem,testCase);

            //获取全部语言
            List<ProblemLanguage> languages = new ArrayList<>();
            for (Map.Entry<String, Language> stringLanguageEntry : languageMap.entrySet()) {

                Language language = stringLanguageEntry.getValue();
                languages.add(new ProblemLanguage()
                        .setLid(language.getId())
                        .setCode(language.getCodeTemplate()));
            }
            problem.setProblemLanguageList(languages);

            //获取标签
            List<String> tags = (List<String>) jsonObject.get("tags");
            problem.setTagIds(createTags(tagMap, tags, "LQB"));
            problems.add(problem);

        }

        HashMap<String, ImportProblemVO> problemVoMap = getImportProblemVOHashMap(getJSONFile(files),
                Arrays.asList("default","cover"));

        //默认模板
        Problem defaultProblem = getProblem(languageMap, tagMap,problemVoMap, "default");

        //覆盖模板
        Problem coverProblem = getProblem(languageMap, tagMap,problemVoMap, "cover");

        problems.forEach(item -> {
            //设置默认和覆盖
            importProblemBeforeHandle(defaultProblem, coverProblem, item);
            problemService.saveOrUpdate_(item);
        });

    }

    @Transactional
    public void importProblem(String workFileDir){

        File fileDir = new File(workFileDir);

        File[] files = fileDir.listFiles();

        //系统语言
        Map<String, Language> languageMap = getLanguageMap();

        ArrayList<Problem> problems = new ArrayList<>();

        //系统标签
        Map<String, Long> tagMap = getTagMap();
        for (File item : files) {

            if(!item.isDirectory())
                continue;

            File[] t = item.listFiles();

            HashMap<String, File> jsonFile = getJSONFile(t);
            File problemF = jsonFile.get("problem.json");
            JSONObject jsonObject = JSONUtil.parseObj(FileUtil.readString(problemF, StandardCharsets.UTF_8));
            Problem problem = toBaseProblem(jsonObject);

            //获取测试用例
            HashMap<String, File> testcaseFile = getTestcaseFile(t);
            File testCase = testcaseFile.get("testCase");
            setProblemCase(problem,testCase);

            //获取全部语言
            List<ProblemLanguage> languages = new ArrayList<>();
            for (Map.Entry<String, Language> stringLanguageEntry : languageMap.entrySet()) {

                Language language = stringLanguageEntry.getValue();
                languages.add(new ProblemLanguage()
                        .setLid(language.getId())
                        .setCode(language.getCodeTemplate()));
            }
            problem.setProblemLanguageList(languages);

            //获取标签
            List<String> tags = (List<String>) jsonObject.get("tags");
            problem.setTagIds(createTags(tagMap, tags, "LQB"));
            problems.add(problem);

        }

        HashMap<String, ImportProblemVO> problemVoMap = getImportProblemVOHashMap(getJSONFile(files),
                Arrays.asList("default","cover"));

        //默认模板
        Problem defaultProblem = getProblem(languageMap, tagMap,problemVoMap, "default");

        //覆盖模板
        Problem coverProblem = getProblem(languageMap, tagMap,problemVoMap, "cover");

        problems.forEach(item -> {
            //设置默认和覆盖
            importProblemBeforeHandle(defaultProblem, coverProblem, item);
            problemService.saveOrUpdate_(item);
        });

    }

    private void setProblemCase(Problem problem,File testCase) {

        Map<String, ProblemCase> problemCasesMap = getProblemCasesMap(testCase);

        List<ProblemCase> problemCase = problem.getProblemCase();

        ArrayList<ProblemCase> problemCases = new ArrayList<>();
        for (ProblemCase aCase : problemCase) {

            String input = aCase.getInput();
            ProblemCase t = problemCasesMap.get(input);
            if(t != null){
                aCase.setInput(t.getInput());
                aCase.setOutput(t.getOutput());
                aCase.setSeq(t.getSeq());
            }
            problemCases.add(aCase);

        }

        problem.setProblemCase(problemCases);

    }

    private Problem toBaseProblem(JSONObject problemJson) {

        Problem problem = new Problem();

        problem.setAuth(0)
                .setSource(problemJson.getStr("source", null))
                .setProblemId("L" + problemJson.getStr("display_id"))
                .setDifficultyId(162L)
                .setProblemTypeId(1L)
                .setIsRemoveEndBlank(1)
                .setOpenCaseResult(0)
                .setCodeShare(0)
                .setType(problemJson.getStr("rule_type").equals("ACM") ? 0 : 1)
                .setTitle(problemJson.getStr("title"))
                .setDescription(UnicodeUtil.toString(problemJson.getJSONObject("description").getStr("value")))
                .setInput(UnicodeUtil.toString(problemJson.getJSONObject("input_description").getStr("value")))
                .setOutput(UnicodeUtil.toString(problemJson.getJSONObject("output_description").getStr("value")))
                .setPrompt(UnicodeUtil.toString(problemJson.getJSONObject("hint").getStr("value")))
                .setTimeLimit(problemJson.getInt("time_limit"))
                .setMemoryLimit(problemJson.getInt("memory_limit") * 1024);

        JSONArray samples = problemJson.getJSONArray("samples");
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < samples.size(); i++) {
            JSONObject sample = (cn.hutool.json.JSONObject) samples.get(i);
            String input = sample.getStr("input");
            String output = sample.getStr("output");
            sb.append("<input>").append(input).append("</input>");
            sb.append("<output>").append(output).append("</output>");
        }
        problem.setExamples(sb.toString());

        int sumScore = 0;
        JSONArray testcaseList = problemJson.getJSONArray("test_case_score");
        List<ProblemCase> problemSamples = new LinkedList<>();
        for (int i = 0; i < testcaseList.size(); i++) {
            JSONObject testcase = (cn.hutool.json.JSONObject) testcaseList.get(i);
            String input = testcase.getStr("input_name");
            input = input.substring(0,input.lastIndexOf('.'));
            String output = testcase.getStr("output_name");
            output = output.substring(0,output.lastIndexOf('.'));
            Integer score = testcase.getInt("score", null);
            problemSamples.add(new ProblemCase().setInput(input).setOutput(output).setScore(score));
            if (score != null) {
                sumScore += score;
            }
        }
        problem.setIsRemote(0);
        problem.setIoScore(sumScore);
        problem.setProblemCase(problemSamples);

        return problem;
    }
}
